home *** CD-ROM | disk | FTP | other *** search
/ IRIX 6.3 Development Libraries / SGI IRIX 6.3 Development Libraries.iso / dist6.3 / gl_dev.idb / usr / share / src / OpenGL / teach / motif / overlay.c.z / overlay.c
Encoding:
C/C++ Source or Header  |  1996-12-06  |  9.3 KB  |  325 lines

  1. /*
  2.  * overlay.c - simple double buffered RGBA motif program which rotates an object.
  3.  *    Overlay and main windows created as a children of a form widget
  4.  *    and managed independently.  The overlay window/context
  5.  *    creation uses the visual_info extension to find a visual with
  6.  *    a transparent pixel.
  7.  */
  8. /* compile: cc -o overlay overlay.c -lGLw -lGLU -lGL -lXm -lXt -lX11 */
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <Xm/Frame.h>
  12. #include <Xm/Form.h>
  13. #include <Xm/RowColumn.h>
  14. #include <X11/GLw/GLwMDrawA.h>
  15. #include <X11/keysym.h>
  16. #include <X11/Xutil.h>
  17. #include <GL/glx.h>
  18. #include <GL/glu.h>
  19.  
  20. static void draw_scene(Widget w, Boolean advance);
  21. static void ov_draw_scene(void);
  22. static void initialize(void);
  23. static Boolean redraw_proc(XtPointer clientData);
  24.  
  25. static int attribs[] = { GLX_RGBA, GLX_RED_SIZE, 1, GLX_DOUBLEBUFFER, None};
  26. static int ov_attribs[] = { GLX_BUFFER_SIZE, 2,
  27.                      GLX_LEVEL, 1,
  28.                     GLX_TRANSPARENT_TYPE_EXT, GLX_TRANSPARENT_INDEX_EXT,
  29.                 None };
  30.  
  31. static String fallbackResources[] = {
  32.     "*sgiMode: True",
  33.     "*useSchemes: all",
  34.     "*glxwidget.width: 300", "*glxwidget.height: 300",
  35.     "*overlay.width: 300", "*overlay.height: 300",
  36.     "*frame.shadowType: SHADOW_IN",
  37.     NULL};
  38.  
  39. static struct state {        /* global UI variables - keep them together */
  40.     Widget w;
  41.     GLXContext cx;
  42.     XtWorkProcId animate_wpid;
  43. } state, ov_state;
  44.  
  45. static XtAppContext appctx;
  46. static Boolean direct;
  47.  
  48. static void
  49. input(Widget w, XtPointer client_data, XtPointer call) {
  50.    char buf[31];
  51.    KeySym keysym;
  52.    XEvent *event = ((GLwDrawingAreaCallbackStruct *) call)->event;
  53.  
  54.    switch(event->type) {
  55.    case KeyRelease:
  56.       XLookupString(&event->xkey, buf, sizeof buf, &keysym, NULL);
  57.       switch(keysym) {
  58.       case XK_Escape:
  59.      exit(EXIT_SUCCESS);
  60.      break;
  61.       default: break;
  62.       }
  63.       break;
  64.    }
  65. }
  66.  
  67. static void
  68. resize(Widget w, XtPointer client_data, XtPointer call) {
  69.     /*struct state *state = (struct state *)client_data;*/
  70.     GLwDrawingAreaCallbackStruct *call_data;
  71.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  72.  
  73.     GLwDrawingAreaMakeCurrent(ov_state.w, ov_state.cx);
  74.     glViewport(0, 0, call_data->width, call_data->height);
  75.     GLwDrawingAreaMakeCurrent(state.w, state.cx);
  76.     glViewport(0, 0, call_data->width, call_data->height);
  77. }
  78.  
  79. static void
  80. expose(Widget w, XtPointer client_data, XtPointer call) {
  81.     GLwDrawingAreaCallbackStruct *call_data;
  82.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  83.  
  84.     draw_scene(w, False);
  85. }
  86.  
  87. static void
  88. ov_expose(Widget w, XtPointer client_data, XtPointer call) {
  89.     GLwDrawingAreaCallbackStruct *call_data;
  90.     call_data = (GLwDrawingAreaCallbackStruct *) call;
  91.  
  92.     GLwDrawingAreaMakeCurrent(w, ov_state.cx);
  93.     ov_draw_scene();
  94.     GLwDrawingAreaMakeCurrent(state.w, state.cx);
  95. }
  96.  
  97. static void
  98. menu(Widget w, XtPointer clientData, XtPointer callData) {
  99.     int entry = (int) clientData;
  100.  
  101.     switch (entry) {
  102.     case 0:
  103.     if (state.animate_wpid) {
  104.         XtRemoveWorkProc(state.animate_wpid);
  105.         state.animate_wpid = 0;
  106.     } else {
  107.         /* register work proc */
  108.         state.animate_wpid = XtAppAddWorkProc(appctx, redraw_proc, &state.w);
  109.     }
  110.     break;
  111.     case 1:
  112.     exit(EXIT_SUCCESS);
  113.     break;
  114.     default:
  115.     break;
  116.     }
  117. }
  118.  
  119. static void
  120. activate_menu(Widget w, XtPointer clientData, XEvent *event, Boolean *cont) {
  121.     Widget popup = *((Widget *) clientData);
  122.  
  123.     if (event->type == ButtonPress && event->xbutton.button == Button3) {
  124.     XmMenuPosition(popup, &event->xbutton);
  125.     XtManageChild(popup);
  126.     }
  127. }
  128.  
  129. static void
  130. create_popup(Widget parent) {
  131.     Arg args[10];
  132.     static Widget popup;
  133.     int n;
  134.     XmButtonType button_types[] = {
  135.     XmTOGGLEBUTTON, XmSEPARATOR, XmPUSHBUTTON,
  136.     };
  137.     XmString button_labels[XtNumber(button_types)];
  138.  
  139.     button_labels[0] = XmStringCreateLocalized("animate");
  140.     button_labels[1] = NULL;
  141.     button_labels[2] = XmStringCreateLocalized("quit");
  142.  
  143.     n = 0;
  144.     XtSetArg(args[n], XmNbuttonCount, XtNumber(button_types)); n++;
  145.     XtSetArg(args[n], XmNbuttonType, button_types); n++;
  146.     XtSetArg(args[n], XmNbuttons, button_labels); n++;
  147.     XtSetArg(args[n], XmNsimpleCallback, menu); n++;
  148.     popup = XmCreateSimplePopupMenu(parent, "popup", args, n);
  149.     XtAddEventHandler(parent, ButtonPressMask, False, activate_menu, &popup);
  150.  
  151.     XmStringFree(button_labels[0]);
  152.     XmStringFree(button_labels[2]);
  153. }
  154.  
  155. static void
  156. map_change(Widget w, XtPointer clientData, XEvent *event, Boolean *cont) {
  157.     switch (event->type) {
  158.     case MapNotify:
  159.     /* resume animation if we become mapped and are in the animated state */
  160.         if (state.animate_wpid != 0)
  161.          state.animate_wpid = XtAppAddWorkProc(appctx, redraw_proc, &state.w);
  162.         break;
  163.     case UnmapNotify:
  164.     /* don't animate if we aren't mapped */
  165.         if (state.animate_wpid) XtRemoveWorkProc(state.animate_wpid);
  166.         break;
  167.     }
  168. }
  169.  
  170. main(int argc, char *argv[]) {
  171.     Display        *dpy;
  172.     XVisualInfo    *visinfo;
  173.     GLXContext      glxcontext;
  174.     Widget          toplevel, frame, form;
  175.     Arg            args[20];
  176.     int            n;
  177.     unsigned long   pixel;
  178.     XColor        col;
  179.     Colormap        cmap;
  180.  
  181.     toplevel = XtOpenApplication(&appctx, "overlay", NULL, 0, &argc, argv,
  182.         fallbackResources, applicationShellWidgetClass, NULL, 0);
  183.     dpy = XtDisplay(toplevel);
  184.  
  185.     frame = XmCreateFrame(toplevel, "frame", NULL, 0);
  186.     XtManageChild(frame);
  187.  
  188.     form = XmCreateForm(frame, "form", NULL, 0);
  189.     XtManageChild(form);
  190.  
  191.     /* specify visual directly */
  192.     if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), attribs)))
  193.     XtAppError(appctx, "no suitable RGB visual");
  194.  
  195.     /* attach to form on all 4 sides */
  196.     n = 0;
  197.     XtSetArg(args[n], XtNx, 0); n++;
  198.     XtSetArg(args[n], XtNy, 0); n++;
  199.     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
  200.     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
  201.     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
  202.     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM); n++;
  203.     XtSetArg(args[n], GLwNvisualInfo, visinfo); n++;
  204.     state.w = XtCreateManagedWidget("glxwidget", glwMDrawingAreaWidgetClass,
  205.     form, args, n);
  206.     XtAddCallback(state.w, GLwNexposeCallback, expose, NULL);
  207.     XtAddCallback(state.w, GLwNresizeCallback, resize, &state);
  208.     XtAddCallback(state.w, GLwNinputCallback, input, NULL);
  209.     state.cx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  210.     direct = glXIsDirect(dpy, state.cx);
  211.  
  212.     /* create overlay widget */
  213.     if (!(visinfo = glXChooseVisual(dpy, DefaultScreen(dpy), ov_attribs)))
  214.     XtAppError(appctx, "no suitable overlay visual");
  215.     XtSetArg(args[n-1], GLwNvisualInfo, visinfo);
  216.     ov_state.w = XtCreateManagedWidget("overlay", glwMDrawingAreaWidgetClass,
  217.     form, args, n);
  218.     XtAddCallback(ov_state.w, GLwNexposeCallback, ov_expose, NULL);
  219.     XtAddCallback(ov_state.w, GLwNresizeCallback, resize, &ov_state);
  220.     XtAddCallback(ov_state.w, GLwNinputCallback, input, NULL);
  221.     ov_state.cx = glXCreateContext(dpy, visinfo, 0, GL_TRUE);
  222.  
  223.     create_popup(frame);
  224.  
  225.     XtAddEventHandler(toplevel, StructureNotifyMask, False, map_change, NULL);
  226.     XtRealizeWidget(toplevel);
  227.     XRaiseWindow(dpy, XtWindow(ov_state.w));
  228.  
  229.     GLwDrawingAreaMakeCurrent(state.w, state.cx);
  230.  
  231.     initialize();
  232.  
  233.     /* allocate a color cell from the overlay planes */
  234.     XtVaGetValues(ov_state.w, XmNcolormap, &cmap, NULL);
  235.     if (!XAllocColorCells(dpy, cmap, True, NULL, 0, &pixel, 1))
  236.     XtAppError(appctx, "can't alloc overlay color cell");
  237.     col.pixel = pixel;
  238.     col.red = 65535;
  239.     col.green = 65535;
  240.     col.blue = 65535;
  241.     col.flags = DoRed | DoGreen | DoBlue;
  242.     XStoreColor(dpy, cmap, &col);
  243.  
  244.     XtAppMainLoop(appctx);
  245. }
  246.  
  247. static void
  248. initialize(void) {
  249.     glShadeModel(GL_FLAT);
  250.     gluPerspective(40., 3.0/2.0, 0.001, 100000.0);
  251.     glTranslatef(0.0, 0.0, -3.0);
  252.     glClearColor(0.2,0.2,0.2,0.);
  253. }
  254.  
  255. static void
  256. side(void) { /* make a square translated 0.5 in the z direction */
  257.     glPushMatrix();
  258.     glTranslatef(0.0,0.0,0.5);
  259.     glRectf(-0.5,-0.5,0.5,0.5);
  260.     glPopMatrix();
  261. }
  262.  
  263. static void
  264. cube(void) { /* make a cube out of 4 squares */
  265.     glPushMatrix();
  266.     side();
  267.     glRotatef(90.,1.,0.,0.);
  268.     side();
  269.     glRotatef(90.,1.,0.,0.);
  270.     side();
  271.     glRotatef(90.,1.,0.,0.);
  272.     side();
  273.     glPopMatrix();
  274. }
  275.  
  276. static void
  277. draw_scene(Widget w, Boolean advance) {
  278.     static float rot = 0.;
  279.  
  280.     glClear(GL_COLOR_BUFFER_BIT);
  281.     glColor3f(.1, .1, .8);
  282.     glPushMatrix();
  283.     if (advance && (rot += 5.) > 360.) rot -= 360.;
  284.     glRotatef(rot,0.,1.,0.);
  285.     cube();
  286.     glScalef(0.3,0.3,0.3);
  287.     glColor3f(.8, .8, .1);
  288.     cube();
  289.     glPopMatrix();
  290.     GLwDrawingAreaSwapBuffers(w);
  291.     if (!direct) glFinish();    /* hack to improve net interactivity */
  292. }
  293.  
  294. /*
  295.  * the amount of work being done doesn't justify the need for
  296.  * a separate overlay initialization and redraw routines so we
  297.  * do it all together. XXX doesn't allocate and initialize any
  298.  * color cells.
  299.  */
  300. static void
  301. ov_draw_scene(void) {
  302.     int i;
  303.     /* simply draw a grid of 10 equally spaced lines */
  304.     glLoadIdentity();
  305.     glOrtho(0., 11., 0., 11., -1., 1.);
  306.     glClearIndex(0.); /* transparent value is always zero */
  307.     glClear(GL_COLOR_BUFFER_BIT);
  308.     glIndexi(1);
  309.     glBegin(GL_LINES);
  310.     for(i = 1; i < 10; i++) {
  311.     glVertex2f(0.5+i, 1.0);
  312.     glVertex2f(0.5+i, 10.0);
  313.     glVertex2f(1.0,  0.5+i);
  314.     glVertex2f(10.0, 0.5+i);
  315.     }
  316.     glEnd();
  317. }
  318.  
  319. static Boolean
  320. redraw_proc(XtPointer clientData) {
  321.     Widget *w = (Widget *)clientData;
  322.     draw_scene(*w, True);
  323.     return False;
  324. }
  325.